using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
namespace FE
{
    public abstract class GameAdapter
    {
        public Dictionary<Actions, Input> ActionInputs = new Dictionary<Actions, Input>();
        public GameAdapter()
        {
            ActionInputs[Actions.Attack] = new UnitAttackInput();
            ActionInputs[Actions.End] = new EndTurnInput();
        }

        public enum Actions
        {
            Null,
            Move,
            Attack,
            Play,
            Dance,
            Staff,
            Steal,
            Item,
            Wait,
            Ride,
            Exit,
            Rescue,
            Give,
            Take,
            Drop,
            Trade,
            Merch,
            Talk,
            End
        }
        public const string quickStatsTile = "{0}:\n Def: +{1}\n Avo: +{2}%\n\n";
        public const string quickStatsUnit = "{0}:\n HP: {1}\\{2}\n Lvl: {3}\n";
        protected Map map;
        protected Player currentPlayerTurn;
        protected int currentX, currentY;
        protected UnitStatus currentSelectedUnit;

        public Map CurrentMap
        {
            get { return map; }
        }
        public Player CurrentPlayer
        {
            get { return currentPlayerTurn; }
        }
        public UnitStatus CurrentUnit
        {
            get { return currentSelectedUnit; }
        }
        public int CurrentX
        {
            get { return currentX; }
            set { currentX = value; }
        }

        public int CurrentY
        {
            get { return currentY; }
            set { currentY = value; }
        }
        public Map.MapNode CurrentNode
        {
            get { return map[currentX, currentY]; }
        }
        public void ResetCurrent()
        {
            currentSelectedUnit = null;
        }
        public void DisplayRange(Map.MapNode node, int rangeMin, int rangeMax, Actions action)
        {
            if (action == Actions.Move)
            {
                List<Map.MapNode> nodes = node.SearchMove(CurrentUnit, rangeMax);
                foreach (Map.MapNode moveNode in nodes)
                {
                    List<Map.MapNode> attackNodes = moveNode.SearchAttack(CurrentUnit.unit.GetEquippedWeapon().Range.X, CurrentUnit.unit.GetEquippedWeapon().Range.Y);
                    foreach (Map.MapNode attackNode in attackNodes)
                    {
                        attackNode.highlightAction = Actions.Attack;
                    }
                }
                foreach (Map.MapNode moveNode in nodes)
                {
                    moveNode.highlightAction = Actions.Move;
                }
            }
            if (action == Actions.Attack)
            {
                List<Map.MapNode> attackNodes = CurrentNode.SearchAttack(CurrentUnit.unit.GetEquippedWeapon().Range.X, CurrentUnit.unit.GetEquippedWeapon().Range.Y);
                foreach (Map.MapNode attackNode in attackNodes)
                {
                    attackNode.highlightAction = Actions.Attack;
                }
            }
            UpdateMap();
        }
        public void ActionChosen(GameAdapter.Actions act)
        {
            Game.Input(new UnitActionChosenInput());
            if (act == Actions.End)
            {
                Game.Input(new EndTurnInput());
            }
            else if (act == Actions.Wait)
            {
                Game.Input(new CheckTurnOverInput());
            }
            else if (act == Actions.Attack)
            {
                Weapon w = CurrentUnit.unit.GetEquippedWeapon();
                DisplayRange(CurrentNode, w.Range.X, w.Range.Y, Actions.Attack);
            }

            ClearActions();
            AddAction(Actions.End);
        }
        public void SelectUnit(UnitStatus unit)
        {            
            currentSelectedUnit = unit;

            PerformSelect(unit);

            ClearActions();
        }
        public void StartPlayerTurn(Player p)
        {
            p.NewTurn();
            currentPlayerTurn = p;

            PerformTurn(p);

            ClearActions();
            AddAction(GameAdapter.Actions.End);
        }
        public void MoveUnit(int x, int y)
        {
            map.RelocateUnit(currentX, currentY, x, y);
            
            PerformMove(currentX, currentY, x, y);

            UpdateMap();

            Weapon w = CurrentUnit.unit.GetEquippedWeapon();
            List<Map.MapNode> nodes = CurrentNode.SearchAttack(w.Range.X, w.Range.Y);
            bool hasTarg = false;
            foreach (Map.MapNode node in nodes)
                if (node.unit != null)
                {
                    Player p = map.GetUnitOwner(node.unit);
                    if (!CurrentPlayer.IsAlly(p))
                    {
                        hasTarg = true;
                    }
                }

            if (hasTarg) AddAction(GameAdapter.Actions.Attack);
            AddAction(GameAdapter.Actions.Item);
            AddAction(GameAdapter.Actions.Wait);                        

        }
        public void AttackUnit(int x, int y)
        {
            Map.MapNode mn = map[x, y];
            Battle b = new Battle(CurrentUnit, mn.unit);
            PerformBattle(b.GetResults);

            Game.Input(new CheckTurnOverInput());
        }
        public void InitializeMap(Map map)
        {
            this.map = map;
            PerformMapInitialize(map);
            UpdateMap();
        }
        public abstract void PerformMapInitialize(Map map);
        public abstract void ClearActions();
        public abstract void AddAction(Actions action);
        public abstract void PerformTurn(Player p);
        public abstract void PerformMove(int x0, int y0, int x1, int y1);
        public abstract void PerformBattle(List<BattleResult> battleResults);
        public abstract void ActionChoice();
        public abstract void UpdateMap();
        public abstract void PerformSelect(UnitStatus unit);
        public Game Game;
    }
}
